﻿namespace Rsdn.Janus
{
    using System;
    using System.Collections;
    using JetBrains.Annotations;
    using ObjectModel;
    using SmartApp;
    using TreeGrid;

    public abstract class OutboxManagerBase : IOutboxManagerBase, IInitable, ITreeNode
    {
        internal const int ForumColumn = 0;
        internal const int SubjectColun = 1;
        internal const int AddInfoColumn = 2;
        protected ITreeNode[] _collections;
        //protected ITreeNode[] _draftCollections;
        protected NewMessageCollection _newMessages;
        //protected NewMessageCollection _newDraftMessages;
        protected IServiceProvider _serviceProvider;
        protected readonly object _formLockFlag = new object();
        protected OutboxDummyFormBase _outboxForm;
        private static int _previewSourceCounter;
        private static readonly Hashtable _previewSources = new Hashtable();
        private NodeFlags flags;

        public OutboxManagerBase(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
            //_newDraftMessages = new NewMessageCollection(serviceProvider, this);
        }

        #region IInitable Members

        /// <summary>
        /// Inits this instance.
        /// </summary>
        public virtual void Init()
        {
            ISynchronizer synchronizer = ServiceProvider.GetRequiredService<ISynchronizer>();

            synchronizer.EndSync.Subscribe(
                delegate
                    {
                        RefreshMessages();
                    });
        }

        /// <summary>
        /// Refreshes the messages.
        /// </summary>
        public void RefreshMessages()
        {
            _newMessages.Refresh();
        }

        #endregion

        public abstract IOutboxForm OutboxForm { get; }

        IOutboxMessageCollection IOutboxManagerBase.NewMessages
        {
            get { return NewMessages; }
        }

        /// <summary>
        /// Gets a value indicating whether this instance has children.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance has children; otherwise, <c>false</c>.
        /// </value>
        bool ITreeNode.HasChildren
        {
            get { return true; }
        }

        /// <summary>
        /// Gets or sets the flags.
        /// </summary>
        /// <value>The flags.</value>
        NodeFlags ITreeNode.Flags
        {
            get { return flags; }
            set { flags = value; }
        }

        /// <summary>
        /// Gets the parent.
        /// </summary>
        /// <value>The parent.</value>
        [CanBeNull]
        ITreeNode ITreeNode.Parent
        {
            get { return null; }
        }

        /// <summary>
        /// Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread safe).
        /// </summary>
        /// <value></value>
        /// <returns>
        /// true if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread safe); otherwise, false.
        /// </returns>
        bool ICollection.IsSynchronized
        {
            get { return false; }
        }

        /// <summary>
        /// Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
        /// </summary>
        /// <value></value>
        /// <returns>
        /// The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
        /// </returns>
        int ICollection.Count
        {
            get { return _collections.Length; }
        }

        /// <summary>
        /// Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
        /// </summary>
        /// <value></value>
        /// <returns>
        /// An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
        /// </returns>
        [NotNull]
        object ICollection.SyncRoot
        {
            get { return _collections.SyncRoot; }
        }

        protected NewMessageCollection NewMessages
        {
            get { return _newMessages; }
        }

        /// <summary>
        /// Gets the <see cref="Rsdn.TreeGrid.ITreeNode"/> with the specified i index.
        /// </summary>
        /// <value></value>
        ITreeNode ITreeNode.this[int iIndex]
        {
            get { return _collections[iIndex]; }
        }

        /// <exception cref="NotSupportedException"><c>NotSupportedException</c>.</exception>
        void ICollection.CopyTo(Array array, int index)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
        /// </returns>
        [NotNull]
        IEnumerator IEnumerable.GetEnumerator()
        {
            return _collections.GetEnumerator();
        }

        public IServiceProvider ServiceProvider
        {
            get { return _serviceProvider; }
        }

        /// <summary>
        /// Перечитать данные из коллекций.
        /// </summary>
        public void Renew()
        {
            if (_outboxForm != null)
            {
                _outboxForm.RefreshList();
            }

            Features.Instance.FeatureChanged(OutboxFeature.Instance);
            Features.Instance.FeatureChanged(DraftboxFeature.Instance);
        }

        /// <summary>
        /// Зарегистрировать источник данных для предварительного просмотра.
        /// </summary>
        /// <param name="src">The SRC.</param>
        /// <returns></returns>
        public static int RegisterPreviewSource(IPreviewSource src)
        {
            int num = _previewSourceCounter++;
            _previewSources.Add(num, src);
            return num;
        }

        /// <summary>
        /// Убрать регистрацию источника данных для предварительного просмотра.
        /// </summary>
        /// <param name="num">The num.</param>
        public static void UnregisterPreviewSource(int num)
        {
            _previewSources.Remove(num);
        }

        /// <summary>
        /// Получить данные предварительного просмотра.
        /// </summary>
        /// <param name="num">The num.</param>
        /// <returns></returns>
        public static string GetPreviewData(int num)
        {
            if (!_previewSources.Contains(num))
            {
                return null;
            }

            return ((IPreviewSource) _previewSources[num]).GetData();
        }
    }
}